#include "trans.h"
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
int recvFileFromServer(int socketFd,char *fileName) {
    // 服务端接收，用户输入puts filename
    off_t fileSize = 0;
    // 接收文件大小
    ssize_t ret = recv(socketFd, &fileSize, sizeof(off_t), MSG_WAITALL);
    if (ret != sizeof(off_t)) {
        printf("接收文件大小失败\n");
        return -1;
    }
    char filerecord[256]={0};
    sprintf(filerecord,"%s.rcd",fileName);
    // 打开文件
    int filerdFd;
    int fileFd ;
    if (access(filerecord, F_OK) == 0) {
        // 文件存在，不截断
        filerdFd = open(filerecord, O_RDWR);
        fileFd = open(fileName, O_RDWR, 0666);
    } else {
        // 文件不存在，创建
        filerdFd = open(filerecord, O_RDWR | O_CREAT, 0666);
        fileFd = open(fileName, O_RDWR | O_CREAT | O_TRUNC, 0666);
    }
    int rdLen=0;
    int rdRet=read(filerdFd,&rdLen,sizeof(int));
    if (fileFd == -1) {
        perror("打开文件失败");
        return -1;
    }
    if(rdRet==0){
        // 没有记录
        send(socketFd,&rdLen,sizeof(int),0);
    }
    else{
        // mmap 从完整页处开始发送
        if(fileSize>100*1024*1024){
            if(rdLen<4096){
                rdLen=0;                                                
            }   
            int re = rdLen%4096;
            rdLen=rdLen-re;
            send(socketFd,&rdLen,sizeof(int),0);
        }   
        else{
            send(socketFd,&rdLen,sizeof(int),0);
        }   

    }
    char buf[1024*1024] = {0};
    off_t lastPrint = 0;
    off_t received = 0;
    //  文件大于100M，
    if(fileSize>100*1024*1024){
        // 使用mmap 接收
        ftruncate(fileFd, fileSize);
        char *p=(char *)mmap(NULL,fileSize,PROT_READ|PROT_WRITE,MAP_SHARED,fileFd,0);
        ERROR_CHECK(p, MAP_FAILED, "mmap");
        char *current_pos = p;
        while (rdLen < fileSize) {
            // 计算剩余需要接收的字节数
            size_t toRead = (fileSize - rdLen) < 1024*1024 ? (fileSize - rdLen) : 1024*1024;
            // 接收数据
            ssize_t ret = recv(socketFd, current_pos, toRead, MSG_WAITALL);
            if (ret == -1) {
                perror("接收数据失败");
                close(fileFd);
                close(filerdFd);
                return -1;
            } else if (ret == 0) {
                // 连接关闭，但文件未接收完
                printf("连接意外关闭，文件未接收完整\n");
                break;
            }
            rdLen += ret;
            current_pos += ret;
            lseek(filerdFd, 0, SEEK_SET);
            write(filerdFd, &rdLen, sizeof(int));
            if (fsync(filerdFd) != 0) {
                perror("刷新缓冲区失败");
                close(fileFd);
                return -1;
            }
            if (rdLen - lastPrint >= fileSize / 10000 || rdLen == fileSize) {
                printf("\r进度:%.2f%%", 100.0 * rdLen / fileSize);
                fflush(stdout);
                /* usleep(50000); */
                lastPrint = rdLen;
            }
        }
        if (msync(p, fileSize, MS_SYNC) == -1) {
            perror("同步失败");
        }
        munmap(p,fileSize);
        close(fileFd);
        close(filerdFd);
        return rdLen;
    }
    else{

        fileSize -= rdLen;
        while (received < fileSize) {
            // 计算剩余需要接收的字节数
            size_t toRead = (fileSize - received ) < 1024*1024 ? (fileSize - received) : 1024*1024;

            ssize_t ret = recv(socketFd, buf, toRead, MSG_WAITALL);

            if (ret == -1) {
                perror("接收数据失败");
                close(fileFd);
                return -1;
            } 
            else if (ret == 0) {
                // 连接关闭，但文件未接收完
                printf("连接意外关闭，文件未接收完整\n");
                break;
            }

            // 写入文件
            ssize_t written = write(fileFd, buf, ret);
            if (written != ret) {
                perror("写入文件失败");
                close(fileFd);
                return -1;
            }

            received += ret;
            rdLen += written;
            lseek(filerdFd, 0, SEEK_SET);
            int a=write(filerdFd,&rdLen,sizeof(int));
            if (fsync(filerdFd) != 0) {
                perror("刷新缓冲区失败");
                close(fileFd);
                return -1;
            }
            // 每1%更新一次进度
            //          if (received - lastPrint >= fileSize / 10000 || received == fileSize) {
            //              printf("\r进度:%.2f%%", 100.0 * received / fileSize);
            //              fflush(stdout);
            //              /* usleep(50000); */
            //              lastPrint = received;
            //          }
        }

        printf("\r进度:100.00%%\n");
        printf("实际接收%jd\n", received);

        // 检查是否完整接收
        if (received != fileSize ) {
            printf("错误：接收的文件大小不匹配，期望%jd，实际%jd\n", fileSize , received);
            close(fileFd);
            return -1;
        }

        close(fileFd);
        close(filerdFd);
        return received;
    }
}
int sendFileToServer(int sockFd,char *fileName){
    //通过管道向服务端发送文件 puts fileName
    struct stat fileStat;
    int fileFd=open(fileName,O_RDWR);
    ERROR_CHECK(fileFd,-1,"file open");
    fstat(fileFd,&fileStat);
    send(sockFd,&fileStat.st_size,sizeof(off_t),0);

    //文件长度
    off_t offset=0;
    size_t onceSentData=0;
    // 之前发了多少 
    recv(sockFd,&offset,sizeof(int),MSG_WAITALL);
    off_t totalSize=fileStat.st_size;
    fileStat.st_size -= offset;
    /* while(offset<fileStat.st_size){ */
    /* onceSentData=sendfile(sockFd,fileFd,&offset,1024*1024); */
    onceSentData=sendfile(sockFd,fileFd,&offset,fileStat.st_size);
    /* sendfile(sockFd,fileFd,&offset,fileStat.st_size); */
    /* if(offset>fileStat.st_size/10000){ */
    printf("\r进度:%.2f%%",100.0*offset/totalSize);
    /* fflush(stdout); */
    /* usleep(50000); */
    /* } */
    /* } */
    printf("\r进度:100.00%%\n");
    close(fileFd);
    return 0;
}

//int sendFileToClient(usrInfo_t *usrInfo,char *hash){
//    //通过管道向服务端发送文件 puts hash
//    printf("文件名%s\n",hash);
//    struct stat fileStat;
//    int fileFd=open(hash,O_RDWR);
//    ERROR_CHECK(fileFd,-1,"file open");
//    fstat(fileFd,&fileStat);
//    send(usrInfo->netFd,&fileStat.st_size,sizeof(off_t),0);
//    
//    printf("发送文件大小%zu\n",fileStat.st_size);
//    //文件长度
//    off_t offset=0;
//    size_t onceSentData=0;
//    // 之前发了多少 
//    recv(usrInfo->netFd,&offset,sizeof(int),MSG_WAITALL);
//    printf("接收记录%jd\n",offset);
//    off_t totalSize=fileStat.st_size;
//    fileStat.st_size -= offset;
//    while(offset<fileStat.st_size){
//        onceSentData=sendfile(usrInfo->netFd,fileFd,&offset,1024*1024);
//        if(offset>fileStat.st_size/10000){
//            printf("\r进度:%.2f%%",100.0*offset/fileStat.st_size);
//            fflush(stdout);
//            usleep(50000);
//        }
//    }
//    printf("\r进度:100.00%%\n");
//    close(fileFd);
//    return 0;
//}
//int sendFileToClient(usrInfo_t *usrInfo,char *hash){
//    //通过管道向客户端发送文件,用户输入gets filename
//    /* printf("文件所在路径%s\n",usrInfo->truthPath); */
//    //   char filePath[4096];  // 用于复制路径
//    //   strcpy(filePath, usrInfo->truthPath);
//    //   char *fileName = strrchr(filePath, '/');
//    //   if(fileName){
//    //       fileName++;  // 跳过 '/'
//    //   }
//    //   /* char *fileName="file1"; */
//    struct stat fileStat;
//    int fileFd=open(hash,O_RDWR);
//    ERROR_CHECK(fileFd,-1,"file open");
//    fstat(fileFd,&fileStat);
//    send(usrInfo->netFd,&fileStat.st_size,sizeof(off_t),MSG_NOSIGNAL);
//    printf("文件大小%ld\n",fileStat.st_size);
//    //文件长度
//    if(fileStat.st_size>100*1024*1024){
//        // 使用mmap 发送
//
//        return 0;
//    }
//    off_t offset=0;
//    size_t onceSentData=0;
//    while(offset<fileStat.st_size){
//        onceSentData=sendfile(usrInfo->netFd,fileFd,&offset,40960);
//        if(onceSentData>fileStat.st_size/10000){
//            printf("\r进度:%.2f%%",100.0*offset/fileStat.st_size);
//            fflush(stdout);
//            /* usleep(50000); */
//        }
//    }
//    printf("\r进度:100.00%%\n");
//    close(fileFd);
//    return 0;
//}
